<?php
/**
 * Created by PhpStorm.
 * User: yy
 * Date: 2019/4/17
 * Time: 11:36
 */

namespace app\common\service\environmentAnalysis;

use app\common\service\BaseService;
use app\common\service\CommonService;
use think\Db;
use think\facade\Config;
use app\common\service\airquality\AirQualityStationAqiRealtimeDayService;

class EnvironmentAnalysisService extends BaseService
{
    /**
     * 获取SO2或NOX或烟尘的不同行业排放量
     * @author yy by 2019/4/17
     * @param array $param
     * @return mixed
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getIndustryEmission($param = [])
    {
        $commonService      = new CommonService();
        $mongodb_huanxin    = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $new_time           = $commonService->getMongoTime($param, 0);
        $industry_limit_arr = $commonService->getIndustryLimitIdmysql();
        if (strtolower($param['contribute_pollutant_name']) == 'so2') {
            $simulate_pollutant = 'emissions_so2_total';
            $table              = 'company_industry_monitor_sulfur_minute';//脱硫
            $emission           = 'emissions';
        } else {
            $simulate_pollutant = 'emissions_nox_total';
            $table              = 'company_industry_monitor_nitre_minute';//脱硝
            $emission           = 'emission';
        }
        $document           = [
            'aggregate'    => $table,
            'pipeline'     => [
                [
                    '$project' => [
                        'publish_time' => 1,
                        'industry_id'  => 1,
                        $emission      => 1,
                    ],
                ],
                [
                    '$match' => [
                        'publish_time' => [
                            '$gte' => $new_time['start_time'],
                            '$lte' => $new_time['end_time'],
                        ],
                    ]
                ],
                [
                    '$group' => [
                        '_id'             => '$industry_id',
                        'emissions_total' => ['$sum' => '$' . $emission],
                    ]
                ],
                [
                    '$sort' => [
                        "_id" => 1,
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];
        $command            = new \MongoDB\Driver\Command($document);
        $rows               = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();
        $contribution_trend = json_decode(json_encode($rows, 320), true);
        $num                = count($contribution_trend[0]['result']);
        # 获取查询日期区间相差的天数
        $dayService   = new AirQualityStationAqiRealtimeDayService();
        $days         = $dayService->diffDays($param['start_time'], $param['end_time']);
        $companyIdArr = $commonService->getCompanyIdArr(1);
        # SO2||NOX 的排放量（模拟数据）不用判断时间区间 20190530改为求和
        $simulate = Db::query("select sum($simulate_pollutant)*$days as total,industry_name,industry_id 
                            from company_industry_monitor_simulation_day_avg
                            where company_id in $companyIdArr and industry_id in $industry_limit_arr
                            group by industry_id");
        $real     = [];
        if ($num > 0) {
            $real = array_column($contribution_trend[0]['result'], null, '_id');
        }
        $simulate = array_column($simulate, null, 'industry_id');
        foreach ($simulate as $k1 => &$v1) {
            $v1['total']              = isset($real[$k1]) ? $v1['total'] + $real[$k1]['emissions_total'] : $v1['total'];
            $v1['val']['name']        = $v1['industry_name'];
            $v1['val']['value']       = $v1['total'];
            $v1['val']['industry_id'] = $v1['industry_id'];
        }
        # 处理电力、焦化、水泥、钢铁为空的情况
        $industry_all         = Db::query("select id,name from basic_industry where id in $industry_limit_arr order by id asc");
        $industry_name_select = array_column($simulate, 'industry_name');
        foreach ($industry_all as $k4 => $v4) {
            if (!in_array($v4['name'], $industry_name_select)) {
                $simulate[] = [
                    'industry_name' => $v4['name'],
                    'total'         => '-',
                    'industry_id'   => $v4['id'],
                    'val'           => [
                        'name'        => $v4['name'],
                        'value'       => '-',
                        'industry_id' => $v4['id']
                    ]
                ];
            }
        }
        # 从数据表的行业id高到低排序
        $total = array_column($simulate, 'industry_id');
        array_multisort($total, SORT_ASC, $simulate);
        $list['date'] = array_column($simulate, 'industry_name');
        # 排放量单位转化为吨
        $list['data'][0] = $commonService->getRealData(array_column($simulate, 'val'), 'value');
        return $list;
    }

    /**
     * 行业排放趋势（默认电力供热行业）
     * （烟尘）行业贡献度趋势需要和气象局提供相关数据 (已取消)
     * @param array $param
     * @return array
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getIndustryEmissionTrend($param = [])
    {
        $list            = [];
        $commonService   = new CommonService();
        $mongodb_huanxin = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $new_time        = $commonService->getMongoTime($param, 0);
        if (strtolower($param['company_pollutant_name']) == 'so2') {
            $simulate_pollutant = 'emissions_so2_total';
            $table              = 'company_industry_monitor_sulfur_minute';//脱硫
            $emission           = 'emissions';
        } else {
            $simulate_pollutant = 'emissions_nox_total';
            $table              = 'company_industry_monitor_nitre_minute';//脱硝
            $emission           = 'emission';
        }
        $document           = [
            'aggregate'    => $table,
            'pipeline'     => [
                [
                    '$project' => [
                        'publish_time' => 1,
                        'industry_id'  => 1,
                        $emission      => 1,
                        'time'         => ['$substr' => ['$publish_time', 0, 10]],
                    ],
                ],
                [
                    '$match' => [
                        'industry_id'  => (int)$param['industry_id'],
                        'publish_time' => [
                            '$gte' => $new_time['start_time'],
                            '$lte' => $new_time['end_time'],
                        ],
                    ]
                ],
                [
                    '$group' => [
                        '_id'             => ['date' => '$time', 'industry_id' => '$industry_id'],
                        'emissions_total' => ['$sum' => '$' . $emission],
                    ]
                ],
                [
                    '$sort' => [
                        "_id" => 1,
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];
        $command            = new \MongoDB\Driver\Command($document);
        $rows               = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();
        $contribution_trend = json_decode(json_encode($rows, 320), true);
        $num                = count($contribution_trend[0]['result']);
        $companyIdArr       = $commonService->getCompanyIdArr(1);
        # SO2||NOX 的排放量（模拟数据）每一天都是相同模拟数据 20190530改为求和
        $data_simulate = Db::query("select sum($simulate_pollutant) as emissions,industry_id
                                from company_industry_monitor_simulation_day_avg
                                where company_id in $companyIdArr and industry_id  = ?
                                ", [$param['industry_id']]);
        # 目前是电力行业查两个表，其他行业查一个表
        $date_all = $commonService->getDate($param['start_time'], $param['end_time']);
        # 比较差集
        $emission_real = [];
        if ($num > 0) {
            foreach ($contribution_trend[0]['result'] as $k => $v) {
                $emission_real[$k]['date']            = $v['_id']['date'];
                $emission_real[$k]['industry_id']     = $v['_id']['industry_id'];
                $emission_real[$k]['emissions_total'] = $v['emissions_total'];
            }
            foreach ($emission_real as $k => &$v) {
                $v['emissions_total'] += $data_simulate[0]['emissions'];
            }
            $list['date']    = array_column($emission_real, 'date');
            $list['data'][0] = array_column($emission_real, 'emissions_total');
            $different       = array_values(array_diff($date_all, $list['date']));
            $different_num   = count($different);
            if ($different_num > 0) {
                for ($i = 0; $i < $different_num; $i++) {
                    $list['date'][]    = $different[$i];
                    $list['data'][0][] = $data_simulate[0]['emissions'];
                }
            }
        } else {
            # 其他行业只计算模拟数据
            $list['date'] = $date_all;
            for ($i = 0; $i < count($list['date']); $i++) {
                $list['data'][0][] = $data_simulate[0]['emissions'];
            }
        }
        # 按照publish_time排序
        array_multisort($list['date'], $list['data'][0]);
        for ($m = 0; $m < count($list['date']); $m++) {
            $list['date'][$m] = date('m/d', strtotime($list['date'][$m]));
        }
        # 排放量单位转化为吨
        $commonService   = new CommonService();
        $list['data'][0] = $commonService->getRealData($list['data'][0]);
        return $list;
    }

    /**
     * 行业贡献度趋势
     * @author yy by 2019/5/25
     * @param array $param
     * @return array
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getIndustryContributeTrend($param = [])
    {
        $commonService = new CommonService();
        $param         = $commonService->getMongoTime($param);
        $companyIdArr  = $commonService->getCompanyIdArr(0);
        $list          = [];
        #贡献度趋势
        $mongodb_huanxin = new \MongoDB\Driver\Manager(Config::get('mongodb_url'));
        $document        = [
            'aggregate'    => Config::get('contribution_table_name'),
            'pipeline'     => [
                [
                    '$project' => [
                        'predict_time'        => 1,
                        'publish_time'        => 1,
                        'contribution_name'   => 1,
                        'company_id'          => 1,
                        'industry_id'         => 1,
                        'station_id'          => 1,
                        'region_id'           => 1,
                        'contribution_value'  => 1, //贡献度
                        'contribution_degree' => 1, //贡献值
                        'concentration'       => 1, //该站点这一天的浓度和
                        'difference'          => ['$eq' => ['$publish_time', '$predict_time']]
                    ],
                ],
                [
                    '$match' => [
                        'difference'        => true,
                        'contribution_name' => strtoupper($param['contribute_pollutant_name']),
                        'industry_id'       => (int)$param['industry_id'],
                        'company_id'        => ['$in' => $companyIdArr],
                        'region_id'         => (int)$param['region_id'],
                        'station_id'        => (int)$param['station_id'],
                        'predict_time'      => [
                            '$gte' => $param['start_time'],
                            '$lte' => $param['end_time'],
                        ],
                    ]
                ],
                [
                    '$group' => [
                        '_id'               => '$publish_time',
//                        'total' => ['$sum' => '$contribution_value'] //因为同一区域同一站点同一行业同一污染物同一天(不同企业)的数据存在多条,此处贡献度为每天的多个公司的和 20190530算法
                        'total'             => ['$sum' => '$contribution_degree'], //因为同一区域同一站点同一行业同一污染物同一天(不同企业)的数据存在多条,此处贡献值为每天的多个公司的和 20190619算法
                        'concentration_sum' => ['$avg' => '$concentration'], //mongodb表此字段已经是浓度和，因此此处求平均值即为这一天的该污染物的浓度和
                    ]
                ],
                [
                    '$sort' => [
                        '_id' => 1,
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];
        $command         = new \MongoDB\Driver\Command($document);
        $rows            = $mongodb_huanxin->executeCommand('huanxin', $command)->toArray();

//            $db = $mongodb_huanxin->huanxin; // 获取名称为 "huanxin" 的数据库
//            $table = $db->air_quality_pollutant_station_forecast_day; //选择表
//            $arr = $table->count();
        $contribution_trend = json_decode(json_encode($rows, 320), true);
        $commonService      = new CommonService();
        $date_all           = $commonService->getDate($param['start_time'], $param['end_time']);
        $num                = count($contribution_trend[0]['result']);
        if ($num > 0) {
            for ($i = 0; $i < $num; $i++) {
                $list['date'][$i] = $list['date'][$i] = date('Y-m-d', strtotime($contribution_trend[0]['result'][$i]['_id']));;
                $list['data'][0][$i] = $contribution_trend[0]['result'][$i]['concentration_sum'] > 0 ? $commonService->contributionRound($contribution_trend[0]['result'][$i]['total'] / $contribution_trend[0]['result'][$i]['concentration_sum']) : '';
            }
            # 比较差集
            $different     = array_values(array_diff($date_all, $list['date']));
            $different_num = count($different);
            if ($different_num > 0) {
                for ($i = 0; $i < $different_num; $i++) {
                    $list['date'][]    = $different[$i];
                    $list['data'][0][] = '';
                }
            }
        } else {
            $list['date'] = $date_all;
            for ($i = 0; $i < count($list['date']); $i++) {
                $list['data'][0][$i] = '';
            }
        }
        # 依据publish_time排序
        array_multisort($list['date'], $list['data'][0]);
        for ($m = 0; $m < count($list['date']); $m++) {
            $list['date'][$m] = date('m/d', strtotime($list['date'][$m]));
//            $list['data'][0][$m] = $list['data'][0][$m] === '' ? '' : $list['data'][0][$m] * 100; //返给前端直接是百分比
            $list['data'][0][$m] = $list['data'][0][$m] === '' ? '' : $list['data'][0][$m]; //返给前端直接是百分比
        }
        return $list;
    }

    /**
     * 获取全市AQI趋势图(目前是长治市)
     * 全要素模块不体现未来时间，只用于历史和到当前的日到日的选择时间区间查询（历史数据判断publish_time）
     * @author yy by 2019/4/18
     * @param array $param
     * @return array|mixed
     */
    public function getAqiTrend($param = [])
    {
        # 前端处理
        $param['start_time'] = date('Y-m-d', strtotime($param['start_time']));
        $param['end_time']   = date('Y-m-d', strtotime($param['end_time']));
        $data                = Db::query("select aqi, DATE_FORMAT(publish_time, '%Y-%m-%d') as date
                                    from air_quality_station_aqi_realtime_day
                                    where region_id = ? and station_id = ? and DATE_FORMAT(publish_time, '%Y-%m-%d') between ? and ?", [$param['region_id'], $param['station_id'], $param['start_time'], $param['end_time']]);
        $commonService       = new CommonService();
        $date_all            = $commonService->getDate($param['start_time'], $param['end_time']);
        if (count($data) > 0) {
            $list['date']    = array_column($data, 'date');
            $list['data'][0] = array_column($data, 'aqi');
            # 比较差集
            $different     = array_values(array_diff($date_all, $list['date']));
            $different_num = count($different);
            if ($different_num > 0) {
                for ($i = 0; $i < $different_num; $i++) {
                    $list['date'][]    = $different[$i];
                    $list['data'][0][] = '';
                }
            }
        } else {
            $list['date'] = $date_all;
            for ($i = 0; $i < count($list['date']); $i++) {
                $list['data'][0][$i] = '';
            }
        }
        # 依据publish_time排序
        array_multisort($list['date'], $list['data'][0]);
        for ($m = 0; $m < count($list['date']); $m++) {
            $list['date'][$m]    = date('m/d', strtotime($list['date'][$m]));
            $list['data'][0][$m] = ($list['data'][0][$m] && $list['data'][0][$m] >= 0) ? ceil($list['data'][0][$m]) : ''; //''等于0情况
        }
        return $list;
    }

    /**
     * 获取污染物天数占比(当天查预报表)
     * 只查轻度及以上（比对publish_time）
     * @author yy by 2019/4/19
     * @param array $param
     * @return array|mixed
     */
    public function getPollutantDay($param = [])
    {
        $list = [
            ['name' => '轻度', 'value' => 0],
            ['name' => '中度', 'value' => 0],
            ['name' => '重度', 'value' => 0],
            ['name' => '严重', 'value' => 0],
        ];
        # 查实测表
        $day_realtime = Db::query("select count(id) as 'value',aqi_level as 'name' 
                              from air_quality_station_aqi_realtime_day
                              where aqi >100 and region_id = ? and station_id = ? and DATE_FORMAT(publish_time, '%Y-%m-%d') between ? and ?
                              group by aqi_level", [$param['region_id'], $param['station_id'], $param['start_time'], $param['end_time']]);
        # 以查询日期区间为基数
        # 获取查询日期区间相差的天数
        $dayService = new AirQualityStationAqiRealtimeDayService();
        $days       = $dayService->diffDays($param['start_time'], $param['end_time']);
        foreach ($list as $k => &$v) {
//            $v['title'] = $v['name'] . ':' . $v['value'] . '天(0%)'; //前台鼠标悬浮提示信息
            foreach ($day_realtime as $k2 => $v2) {
                if ($v2['name'] === $v['name']) {
                    $v['value'] = $v2['value'];
//                    $v['value'] = $v2['value'] / $days; //在查询区间里的占比
//                    $v['title'] = $v2['name'] . ':' . $v2['value'] . '天(' . round($v['value'] * 100, 2) . '%)'; //前台鼠标悬浮提示信息
                }
            }
        }
        # 轻度、中度、重度、严重四个等级总天数
        $statistics = array_sum(array_column($list, 'value'));
        $list[]     = ['name' => '其它', 'value' => $days - $statistics];
        return $list;
    }

    /**
     * 获取首要污染物占比(默认aqi_level轻度)
     * 当天之前查实测表，当天和之后查预报表
     * @author yy by 2019/4/19
     * @param array $param
     * @return array|mixed
     */
    public function getPrimaryPollutant($param = [])
    {
        $list = [
            ['name' => 'PM10', 'value' => 0],
            ['name' => 'PM2.5', 'value' => 0],
            ['name' => 'SO2', 'value' => 0],
            ['name' => 'NO2', 'value' => 0],
            ['name' => 'O3', 'value' => 0],
            ['name' => 'CO', 'value' => 0],
        ];
        # 查实测表
        $day_realtime = Db::query("select name, DATE_FORMAT(publish_time, '%Y-%m-%d') as date
                              from air_quality_station_primary_pollutant_realtime_day
                              where region_id = ? and station_id = ? and aqi_level = ? and DATE_FORMAT(publish_time, '%Y-%m-%d') between ? and ?
                              ", [$param['region_id'], $param['station_id'], $param['aqi_level'], $param['start_time'], $param['end_time']]);
        # 将O3 和 O3_8H 存在于同一天和 单天只存在O3_8H的情况统一处理为O3
        $new = [];
        if (count($day_realtime) > 0) {
            foreach ($day_realtime as $k1 => $v1) {
                $new[$v1['name']][] = $v1['date'];
            }
            # O3 和 O3_8H 同时存在
            if (isset($new['O3']) && isset($new['O3_8H'])) {
                # 比较差集
                $different     = array_values(array_diff($new['O3_8H'], $new['O3']));
                $different_num = count($different);
                if ($different_num > 0) {
                    for ($i = 0; $i < $different_num; $i++) {
                        $new['O3'][] = $different[$i];
                    }
                }
            }
            # 只存在O3_8H
            if (!isset($new['O3']) && isset($new['O3_8H'])) {
                $o3_8h_num = count($new['O3_8H']);
                for ($m = 0; $m < $o3_8h_num; $m++) {
                    $new['O3'][] = $new['O3_8H'][$m];
                }
            }
            foreach ($new as $k2 => &$v2) {
                $v2 = count($v2);
            }
            foreach ($list as $k => &$v) {
                foreach ($new as $k2 => $v2) {
                    if (strtolower($k2) == strtolower($v['name'])) {
                        $v['value'] += $v2;
                    }
                }
            }
        }
        return $list;
    }

}
